﻿using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;

namespace ServiceCore.Tool.Pic
{
    public class CacheUntity
    {
        private static ICacheHelper _cache = new MemoryCacheHelper();// new RedisCacheHelper();//默认使用Redis  
        private static bool isInited = false;
        public static void Init(ICacheHelper cache)
        {
            if (isInited)
                return;
            _cache.Dispose();
            _cache = cache;
            isInited = true;
        }


        public static bool Exists(string key)
        {
            return _cache.Exists(key);
        }


        public static T GetCache<T>(string key) where T : class
        {
            return _cache.GetCache<T>(key);
        }


        public static void SetCache(string key, object value)
        {
            _cache.SetCache(key, value);
        }


        public static void SetCache(string key, object value, DateTimeOffset expiressAbsoulte)
        {
            _cache.SetCache(key, value, expiressAbsoulte);
        }
        //public void SetCache(string key, object value, double expirationMinute)
        //{


        //} 
        public static void RemoveCache(string key)
        {
            _cache.RemoveCache(key);
        }
    }
    public interface ICacheHelper
    {
        bool Exists(string key);


        T GetCache<T>(string key) where T : class;


        void SetCache(string key, object value);


        void SetCache(string key, object value, DateTimeOffset expiressAbsoulte);//设置绝对时间过期


        //void SetCache(string key, object value, double expirationMinute);  //设置滑动过期， 因redis暂未找到自带的滑动过期类的API，暂无需实现该接口


        void RemoveCache(string key);


        void Dispose();
    }


     

//public class RedisCacheHelper : ICacheHelper
//    {
//        public RedisCacheHelper(/*RedisCacheOptions options, int database = 0*/)//这里可以做成依赖注入，但没打算做成通用类库，所以直接把连接信息直接写在帮助类里
//        {
//            RedisCacheOptions options = new RedisCacheOptions();
//            options.Configuration = "127.0.0.1:6379";
//            options.InstanceName = "test";
//            int database = 0;
//            _connection = ConnectionMultiplexer.Connect(options.Configuration);
//            _cache = _connection.GetDatabase(database);
//            _instanceName = options.InstanceName;
//        }


//        private IDatabase _cache;


//        private ConnectionMultiplexer _connection;


//        private readonly string _instanceName;


//        private string GetKeyForRedis(string key)
//        {
//            return _instanceName + key;
//        }


//        public bool Exists(string key)
//        {
//            if (string.IsNullOrWhiteSpace(key))
//                throw new ArgumentNullException(nameof(key));


//            return _cache.KeyExists(GetKeyForRedis(key));
//        }


//        public T GetCache<T>(string key) where T : class
//        {
//            if (string.IsNullOrWhiteSpace(key))
//                throw new ArgumentNullException(nameof(key));


//            var value = _cache.StringGet(GetKeyForRedis(key));
//            if (!value.HasValue)
//                return default(T);


//            return JsonConvert.DeserializeObject<T>(value);
//        }


//        public void SetCache(string key, object value)
//        {
//            if (string.IsNullOrWhiteSpace(key))
//                throw new ArgumentNullException(nameof(key));
//            if (value == null)
//                throw new ArgumentNullException(nameof(value));


//            if (Exists(GetKeyForRedis(key)))
//                RemoveCache(GetKeyForRedis(key));


//            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value));
//        }


//        public void SetCache(string key, object value, DateTimeOffset expiressAbsoulte)
//        {
//            if (string.IsNullOrWhiteSpace(key))
//                throw new ArgumentNullException(nameof(key));
//            if (value == null)
//                throw new ArgumentNullException(nameof(value));


//            if (Exists(GetKeyForRedis(key)))
//                RemoveCache(GetKeyForRedis(key));


//            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value), expiressAbsoulte - DateTime.Now);
//        }


//        //public void SetCache(string key, object value, double expirationMinute)
//        //{
//        //    if (Exists(GetKeyForRedis(key)))
//        //        RemoveCache(GetKeyForRedis(key));


//        //    DateTime now = DateTime.Now;
//        //    TimeSpan ts = now.AddMinutes(expirationMinute) - now;
//        //    _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value), ts);
//        //}


//        public void RemoveCache(string key)
//        {
//            if (string.IsNullOrWhiteSpace(key))
//                throw new ArgumentNullException(nameof(key));


//            _cache.KeyDelete(GetKeyForRedis(key));
//        }


//        public void Dispose()
//        {
//            if (_connection != null)
//                _connection.Dispose();
//            GC.SuppressFinalize(this);
//        }
//    }
  
    public class MemoryCacheHelper : ICacheHelper
    {
        public MemoryCacheHelper(/*MemoryCacheOptions options*/)//这里可以做成依赖注入，但没打算做成通用类库，所以直接把选项直接封在帮助类里边
        {
            //this._cache = new MemoryCache(options);
            this._cache = new MemoryCache(new MemoryCacheOptions());
        }


        private IMemoryCache _cache;


        public bool Exists(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));


            object v = null;
            return this._cache.TryGetValue<object>(key, out v);
        }


        public T GetCache<T>(string key) where T : class
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));


            T v = null;
            this._cache.TryGetValue<T>(key, out v);


            return v;
        }


        public void SetCache(string key, object value)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));


            object v = null;
            if (this._cache.TryGetValue(key, out v))
                this._cache.Remove(key);
            this._cache.Set<object>(key, value);
        }


        public void SetCache(string key, object value, double expirationMinute)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));


            object v = null;
            if (this._cache.TryGetValue(key, out v))
                this._cache.Remove(key);
            DateTime now = DateTime.Now;
            TimeSpan ts = now.AddMinutes(expirationMinute) - now;
            this._cache.Set<object>(key, value, ts);
        }


        public void SetCache(string key, object value, DateTimeOffset expirationTime)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));


            object v = null;
            if (this._cache.TryGetValue(key, out v))
                this._cache.Remove(key);


            this._cache.Set<object>(key, value, expirationTime);
        }


        public void RemoveCache(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));


            this._cache.Remove(key);
        }


        public void Dispose()
        {
            if (_cache != null)
                _cache.Dispose();
            GC.SuppressFinalize(this);
        }
    }
}
